

export class Video {
  constructor(screenVertex, material){
    this.name = this.getNewGuid()
    this.ids = []
    this.material = material
    this.initEntity(screenVertex)
  }
  initEntity(screenVertex){ // 初始化
    this.screenVertex = screenVertex
    this.coord = screenVertex.coord
    this.position = screenVertex.position
    this.vertexs = screenVertex.vertexs
    this.setVideoEntity(this.vertexs)
    this.setCameraEntity(this.position)
    this.setRayEntity(this.position, this.vertexs)
  }
  changeEntity(screenVertex){ // 更新
    this.removeEntity()
    this.initEntity(screenVertex)
  }
  getId(){
    const id = this.getNewGuid()
    this.ids.push(id)
    return id
  }
  getNewGuid() { // 生成随机id
    var code = "";
    //设置长度，这里看需求，我这里设置了4
    var codeLength = 8;
    //设置随机字符
    var random = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    //循环codeLength 我设置的4就是循环4次
    for (var i = 0; i < codeLength; i++) {
      //设置随机数范围,这设置为0 ~ 36
      var index = Math.floor(Math.random() * 9);
      //字符串拼接 将每次随机的字符 进行拼接
      code += random[index];
    }
    return code;
  }
  setCameraEntity(position){ // 创建相机图标
    const id = this.getId()
    viewer.entities.add({
      id: id,
      name: this.name,
      position,
      billboard: {
        image: require("../assets/images/camera.png"), // 图片路径
        show: true, // 显示
        scale: 0.3, // 缩放比
        width: 100, // 宽度(px)
        height: 100, // 高度(px)
        scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.5)
        // sizeInMeters: true
      },
    })
  }
  setVideoEntity(hierarchy){ // 创建幕布
      const id = this.getId()
      viewer.entities.add({
          id: id,
          polygon: {
            hierarchy, 
            perPositionHeight: true,
            material: this.material,
            outline: false, // 轮廓线
          },
        })
  }
  setRayEntity(position, vertexs){ // 创建相机到幕布顶点的连线
    vertexs.forEach(point => {
        const id = this.getId()
          viewer.entities.add({
            id: id,
            polyline : {
                positions: [position, point],
                width : 2,
                material :  Cesium.Color.WHITE.withAlpha(0.5),
            }})
    })
  }
  removeEntity(){ // 删除所有模型
    this.ids.forEach(id => {
      viewer.entities.removeById(id)
    })
  }
}



// 屏幕顶点坐标集合
export class ScreenVertex {
  constructor({coord, position, azimuth = 0,pitchAngel = 0, openAngelX = 70, openAngelY = 70}){
    this.coord = coord
    this.position = position || Cesium.Cartesian3.fromRadians(coord.longitude, coord.latitude, coord.height)
    this.viewRay = this.getViewDirection( coord, azimuth, pitchAngel )
    let vertexRays = this.getvertexDirection( openAngelX, openAngelY )
    this.vertexs = this.getvertexs(vertexRays)
    // this.showRay()
  }

  getViewDirection(coord, azimuth, pitchAngel ){ // 获取视线方向的射线
    let start = Cesium.Cartesian3.fromRadians(coord.longitude, coord.latitude, coord.height);//new Cesium.Cartesian3(0.0, 0.0, 0.0);
    // 根据方位角 设置初始向量方位 0度 默认为 正东的向量
    let end = Cesium.Cartesian3.fromRadians(coord.longitude + 0.0001, coord.latitude, coord.height);//rayOrientation(coord,azimuth)
    let eastRay = new Cesium.Ray(
      start,
      Cesium.Cartesian3.subtract(
        start,
        end,
        new Cesium.Cartesian3()
      )
    )
    return getHeadingPitchRoll({heading:azimuth, pitch:pitchAngel, roll:0.0, ray: eastRay})
  }

  getvertexDirection(openAngelX, openAngelY){ // 获取4个顶点方向射线
    const viewRay = this.viewRay
    // 默认上下张角为70度
    let ud = Math.abs(openAngelX / 2)
    let oabs = Math.abs(openAngelY / 2)
    let points = [
      // 上下
      {
        heading:ud,
        pitch: oabs,
        roll:0.0
      },
      // 左右
      {
        heading:-ud,
        pitch: oabs,
        roll:0.0
      },
      {
        heading: -ud,
        pitch:-oabs,
        roll:0.0
      },
      {
        heading: ud,
        pitch: -oabs,
        roll:0.0
      },
    ]
    return points.map(({heading, pitch}) => {
      return getHeadingPitchRoll({heading, pitch, roll:0.0, ray: viewRay})
    })
  }

  getvertexs(vertexRays){ // 通过幕布顶点射线获取幕布顶点
        //1. 获取椭球
        let ellipsoid=viewer.scene.globe.ellipsoid;
        let distance = 500
        vertexRays.forEach(ray => {
            //2. 判断射线与球交点最短距离
            let intersection = Cesium.IntersectionTests.rayEllipsoid(ray, ellipsoid);
            distance = intersection && intersection.start < distance ? intersection.start : distance
        });
        console.log(distance,' distance')
        return vertexRays.map(vertexRay => 
          Cesium.Ray.getPoint(vertexRay, distance)
        )
  }
}

























// 张角 俯仰角 方位角 向量 获取一个新的张角
function getHeadingPitchRoll({heading,pitch,roll,ray}){
  var heading = Cesium.Math.toRadians(heading);
  var pitch = Cesium.Math.toRadians(pitch);
  var roll = Cesium.Math.toRadians(roll);
  let angleGroup = new Cesium.HeadingPitchRoll(heading, pitch, roll);    // 期望的旋转量，弧度单位

  let rayNew = rotateRay_HeadingPitchRoll(ray, angleGroup);
  return rayNew
}

export function drawerPatter(viewer,coord,{azimuth,pitchAngel},func) {
  let start = Cesium.Cartesian3.fromRadians(coord.longitude, coord.latitude, coord.height);//new Cesium.Cartesian3(0.0, 0.0, 0.0);
  // 根据方位角 设置初始向量方位 0度 默认为 正东的向量
  let end = Cesium.Cartesian3.fromRadians(coord.longitude + 0.0001, coord.latitude, coord.height);//rayOrientation(coord,azimuth)
  let direct = Cesium.Cartesian3.subtract(
    start,
    end,
    new Cesium.Cartesian3()
  )
  let ray = new Cesium.Ray(start, direct)
  let nRay = getHeadingPitchRoll({heading:azimuth,pitch:pitchAngel,roll:0.0,ray})

  if (func) {
    // func(drawRay(viewer,ray))
    func(mdrawRay(nRay))
  }
  // 方位角 俯仰角 张角
  return function ({azimuth,pitchAngel,openAngel} = params){
    return  getLineByThreeAngles({azimuth,pitchAngel,openAngel,ray:nRay})
  }
}

// azimuth [-180,180]
function rayOrientation(coord,azimuth){
  coord = JSON.parse(JSON.stringify(coord))
  let r = 0.0001
  let age = azimuth >= 0 ? 1 : -1
  azimuth = Math.abs(azimuth)
  let oAngle = azimuth % 90
  let mul = parseInt((azimuth / 90).toString()),
    rad = oAngle / 360,
    s = Math.sin(rad) * r,
    c = Math.cos(rad) * r

  switch (mul){
    // 第一二象限
    case  0:
      if(c===r){
        coord.longitude += r
      }else {
        coord.longitude += c
        coord.latitude += (age*s)
        console.log(coord)
      }

    //第三四象限
    case 1:
      if(c===r){
        coord.latitude -= r
      }else {
        coord.longitude -= c
        coord.latitude += (-age*s)
      }
      break;
    // y轴 负
    case 2:
      coord.longitude -=r
      break;
  }
  return  Cesium.Cartesian3.fromRadians(coord.longitude, coord.latitude, coord.height);//new Cesium.Cartesian3(1.0, 0.0, 0.0);
}

// 获取向量及坐标 通过方位角 俯仰角 张角
function getLineByThreeAngles({azimuth,pitchAngel,openAngel,ray} = params){
  // 默认上下张角为70度
  let ud = Math.abs(openAngel/2)
  // let ou,od
  // if(pitchAngel>=0){
  //   ou = ud + pitchAngel
  //   od = -(ud - pitchAngel)
  // }else{
  //   ou = ud + pitchAngel
  //   od = -ud + pitchAngel
  // }
  let oabs = Math.abs(70.0 / 2)
  let points = [
    // 上下
    {
      heading:ud,
      pitch: oabs,
      roll:0.0
    },
    // 左右
    {
      heading:-ud,
      pitch: oabs,
      roll:0.0
    },
    {
      heading: -ud,
      pitch:-oabs,
      roll:0.0
    },
    {
      heading: ud,
      pitch: -oabs,
      roll:0.0
    },
  ]
  let res = []
  const drawer = ({heading,pitch,roll})=>{
    let nRay = getHeadingPitchRoll({heading,pitch,roll,ray})
    let {p1,p2} = mdrawRay(nRay)
    res.push({ray:nRay,p1,p2})
  }
  points.forEach(p=>{
    drawer(p)
  })

  return res
}




//  函数功能：根据HeadingPitchRoll对象来旋转一个射线
//  传入参数：
//      rayIn：一个Cesium.Ray对象
//      hpt：一个Cesium.HeadingPitchRoll对象，里头三个角都是弧度。三个角的正方形都是顺时针
//  注   意：
//      旋转方向方面，数学是逆时针正角度，但是这里是顺时针为正角。即，heading正角，会往南边转。pitch正角，会往低头方向转
function rotateRay_HeadingPitchRoll(rayIn, hpr)
{
    var coord = Cesium.Cartographic.fromCartesian(rayIn.origin);
    // console.log("射线起点：" + rayIn.origin.x + "," + rayIn.origin.y + "," + rayIn.origin.z);

    // 方位角旋转
    var vecLocalPlumbline = calcLocalPlumbline(coord.longitude, coord.latitude);
    var vecLocalNormal = new Cesium.Cartesian3.negate(vecLocalPlumbline, new Cesium.Cartesian3());    // 地面的法线，也就是反铅垂线
    var qtHeading = Cesium.Quaternion.fromAxisAngle(vecLocalNormal, hpr.heading);

    // 俯仰角旋转
    var vecLocalNorth = calcLocalNorthern(coord.longitude, coord.latitude);
    var qtPitch = Cesium.Quaternion.fromAxisAngle(vecLocalNorth, hpr.pitch);

    // 横滚暂时用不上
    // var vecLocalEast = calcLocalEastern(coord.longitude, coord.latitude);
    // var qtRoll = Cesium.Quaternion.fromAxisAngle(vecLocalEast, hpr.roll);

    // 整体旋转
    var Q = Cesium.Quaternion.multiply(qtHeading, qtPitch, new Cesium.Quaternion());


    //return rotateRay_Matrix4(rayIn, m4);
    let rotate = Cesium.Transforms.headingPitchRollQuaternion(rayIn.origin, hpr);
    return rotateRay_Quaternion(rayIn, Q);
}


//  函数功能：根据Quaternion对象来旋转一个射线
//  传入参数：
//      rayIn：一个Cesium.Ray对象
//      rotate：Cesium.Quaternion对象，四元数
function rotateRay_Quaternion(rayIn, rotate)
{
    let B = rayIn.origin;
    let A = Cesium.Ray.getPoint(rayIn, 1);
    // console.log("旋转前的rotateRay    " + rayIn.origin + ", " + Cesium.Ray.getPoint(rayIn, 1000));

    // 构造基于B的法向量旋转rotate度的矩阵
    let m3 = Cesium.Matrix3.fromQuaternion(rotate);
    // console.log("3矩阵  " + m3);
    let m4 = Cesium.Matrix4.fromRotationTranslation(m3);
    // console.log("从Matrix3计算代表旋转的Matrix4  " + m4);

    // 计算A点相对B点的坐标A1
    let dir1 = Cesium.Cartesian3.subtract(A, B, new Cesium.Cartesian3());
    // console.log("向量dir1  " + dir1);
    //对A1应用旋转矩阵
    let dir2 = Cesium.Matrix4.multiplyByPoint(m4, dir1, new Cesium.Cartesian3());
    // console.log("向量dir2  " + dir2);

    // 新的的坐标
    let rayOut = new Cesium.Ray(B, dir2);
    // console.log("旋转后的rotateRay    " + rayOut.origin + ", " + Cesium.Ray.getPoint(rayOut, 1000));
    return rayOut;
}

// 计算一个坐标点所在处的铅垂线向量
// 传入参数为弧度单位的经纬度
function calcLocalPlumbline(longitude, latitude)
{
    var pnt = Cesium.Cartesian3.fromRadians(longitude, latitude, 0.0);
    var vecPlumbline = Cesium.Cartesian3.normalize(pnt, new Cesium.Cartesian3());    // 地面的反铅垂线，也就是地面法线
    return vecPlumbline
}


// 计算一个坐标点所在处的正东向量
// 传入参数为弧度单位的经纬度
function calcLocalEastern(longitude, latitude)
{
    var pnt0 = Cesium.Cartesian3.fromRadians(longitude, latitude, 0.0);
    var pnt1 = Cesium.Cartesian3.fromRadians(longitude + 0.001, latitude, 0.0);
    var vecEast = Cesium.Cartesian3.subtract(pnt1, pnt0, new Cesium.Cartesian3());
    var vecEastNormal = Cesium.Cartesian3.normalize(vecEast, new Cesium.Cartesian3());    // 地面的反铅垂线，也就是地面法线
    return vecEastNormal;
}


// 计算一个坐标点所在处的正北向量
// 传入参数为弧度单位的经纬度
function calcLocalNorthern(longitude, latitude)
{
    var pnt0 = Cesium.Cartesian3.fromRadians(longitude, latitude, 0.0);
    var pnt1 = Cesium.Cartesian3.fromRadians(longitude, latitude + 0.001, 0.0);
    var vecNorth = Cesium.Cartesian3.subtract(pnt1, pnt0, new Cesium.Cartesian3());
    var vecNorthNormal = Cesium.Cartesian3.normalize(vecNorth, new Cesium.Cartesian3());    // 地面的反铅垂线，也就是地面法线
    return vecNorthNormal;
}

//画直线
function drawRay(viewer, rayIn)
{
    //return;
    let p1 = rayIn.origin;
    let p2 = Cesium.Ray.getPoint(rayIn, 500);
    console.log("P1   " + p1);
    console.log("P2   " + p2);
    return {
      p1,
      p2
    }
    // let positions = [];
    // positions.push(p1);
    // positions.push(p2);
    //
    // //画一条p1到p2的线段
    // viewer.entities.add({
    // //id: id,
    // name: "线段",
    // show: true,
    // polyline: {
    //     positions: positions, //笛卡尔坐标
    //     // positions: Cesium.Cartesian3.fromDegreesArrayHeights(positions),
    //     width: width,
    //     material: color,//Cesium.Color.fromCssColorString("blue"),
    //     /*  distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
    //     2000.0,
    //     200000.0
    //     ), */
    //     //clampToGround: true,
    // },
    // });
}

//
function mdrawRay(rayIn){
  let origin=rayIn.origin;//相机点
  //1. 获取椭球
  let ellipsoid=viewer.scene.globe.ellipsoid;
  //2. 判断射线与球交点
  let intersection = Cesium.IntersectionTests.rayEllipsoid(rayIn, ellipsoid);
  let vertex
  if(intersection){
    vertex = Cesium.Ray.getPoint(rayIn, intersection.start) // 如果射线接地，取接地点
  } else{
    vertex = Cesium.Ray.getPoint(rayIn, 100) //如果不接地，延长500
  }
  // 生成的点还是不在一个平面，需要进一步运算，但整体数据都有了
  return {
    p1:origin,
    p2:vertex
  }
}
